﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using MediatorLib;
using QLTT.Models;
using System.Security.Cryptography;

 namespace FunctionalFun.UI  
 {  
   public static class PasswordBoxAssistant  
   {  
       public static readonly DependencyProperty BoundPassword =  
           DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));  
   
       public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(  
           "BindPassword", typeof (bool), typeof (PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));  
   
       private static readonly DependencyProperty UpdatingPassword =  
           DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant));  
   
       private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
       {  
           PasswordBox box = d as PasswordBox;  
   
           // only handle this event when the property is attached to a PasswordBox  
           // and when the BindPassword attached property has been set to true  
           if (d == null || !GetBindPassword(d))  
           {  
               return;  
           }  
   
           // avoid recursive updating by ignoring the box's changed event  
           box.PasswordChanged -= HandlePasswordChanged;  
   
           string newPassword = (string)e.NewValue;  
   
           if (!GetUpdatingPassword(box))  
           {  
               box.Password = newPassword;  
           }  
   
           box.PasswordChanged += HandlePasswordChanged;  
       }  
   
       private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)  
       {  
           // when the BindPassword attached property is set on a PasswordBox,  
           // start listening to its PasswordChanged event  
   
           PasswordBox box = dp as PasswordBox;  
   
           if (box == null)  
           {  
               return;  
           }  
   
           bool wasBound = (bool)(e.OldValue);  
           bool needToBind = (bool)(e.NewValue);  
   
           if (wasBound)  
           {  
               box.PasswordChanged -= HandlePasswordChanged;  
           }  
   
           if (needToBind)  
           {  
               box.PasswordChanged += HandlePasswordChanged;  
           }  
       }  
   
       private static void HandlePasswordChanged(object sender, RoutedEventArgs e)  
       {  
           PasswordBox box = sender as PasswordBox;  
   
           // set a flag to indicate that we're updating the password  
           SetUpdatingPassword(box, true);  
           // push the new password into the BoundPassword property  
           SetBoundPassword(box, box.Password);  
           SetUpdatingPassword(box, false);  
       }  
   
       public static void SetBindPassword(DependencyObject dp, bool value)  
       {  
           dp.SetValue(BindPassword, value);  
       }  
   
       public static bool GetBindPassword(DependencyObject dp)  
       {  
           return (bool)dp.GetValue(BindPassword);  
       }  
   
       public static string GetBoundPassword(DependencyObject dp)  
       {  
           return (string)dp.GetValue(BoundPassword);  
       }  
   
       public static void SetBoundPassword(DependencyObject dp, string value)  
       {  
           dp.SetValue(BoundPassword, value);  
       }  
   
       private static bool GetUpdatingPassword(DependencyObject dp)  
       {  
           return (bool)dp.GetValue(UpdatingPassword);  
       }  
   
       private static void SetUpdatingPassword(DependencyObject dp, bool value)  
       {  
           dp.SetValue(UpdatingPassword, value);  
       }  
   }  
 }  
namespace QLTT.ViewModels
{
    /// <summary>
    /// Provides common functionality for ViewModel classes
    /// </summary>
    public class Utils
    {
        public static string CreateMD5Hash(string input)
        {
            // Use input string to calculate MD5 hash
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);

            // Convert the byte array to hexadecimal string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("X2"));
                // To force the hex string to lower-case letters instead of
                // upper-case, use he following line instead:
                // sb.Append(hashBytes[i].ToString("x2")); 
            }
            return sb.ToString();
        }
    }
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        static readonly Mediator mediator = new Mediator();
        public static string[] DayOfWeeks = { "T2", "T3", "T4", "T5", "T6", "T7", "CN" };
        private int _rowPerPage = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RowsPerPage"]);
        private double _fontSize = -1;
        private static User _user = null;
        private string _errorMsg;

        public Mediator Mediator
        {
            get { return mediator; }
        }
        public int RowsPerPage
        {
            get { return _rowPerPage; }
            set { _rowPerPage = value; }
        }
        public static User CurrentUser
        {
            get { return _user; }
            set 
            {
                _user = value;
                if (_user == null)
                    CurrentRole = UserRole.Unauthorized;
                else
                    CurrentRole = (UserRole)_user.Role;
            }
        }
        public static UserRole CurrentRole{get; set;}
        public string ErrorMsg
        {
            get { return _errorMsg; }
            set
            {
                if (value == _errorMsg)
                    return;
                _errorMsg = value;
                this.OnPropertyChanged("ErrorMsg");
            }
        }
        public double FontSize
        {
            get 
            {
                if (_fontSize < 0)
                {
                    double.TryParse(System.Configuration.ConfigurationManager.AppSettings["FontSize"], out _fontSize);
                    if (_fontSize <= 8 || _fontSize >= 16)
                        _fontSize = -1;
                }
                return _fontSize; 
            }
        }
        
        public bool ValidateData(string[] properties)
        {
            foreach (string property in properties)
            {
                string error = (this as System.ComponentModel.IDataErrorInfo)[property];
                if (!string.IsNullOrEmpty(error))
                {
                    this.ErrorMsg = error;
                    return false;
                }
            }
            return true;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #region
        /// <summary>
        /// Returns the user-friendly name of this object.
        /// Child classes can set this property to a new value,
        /// or override it to determine the value on-demand.
        /// </summary>
        public virtual string DisplayName { get; protected set; }

        #endregion // DisplayName
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #region IDisposable Members

        /// <summary>
        /// Invoked when this object is being removed from the application
        /// and will be subject to garbage collection.
        /// </summary>
        public void Dispose()
        {
            this.OnDispose();
        }

        /// <summary>
        /// Child classes can override this method to perform 
        /// clean-up logic, such as removing event handlers.
        /// </summary>
        protected virtual void OnDispose()
        {
        }

#if DEBUG
        /// <summary>
        /// Useful for ensuring that ViewModel objects are properly garbage collected.
        /// </summary>
        ~ViewModelBase()
        {
            string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
            System.Diagnostics.Debug.WriteLine(msg);
        }
#endif

        #endregion // IDisposable Members

    }
}
